package cn.iocoder.yudao.module.system.service.gugu;

import cn.iocoder.yudao.module.system.controller.admin.gugu.vo.subjectselection.MajorCategoryListReqVO;
import cn.iocoder.yudao.module.system.controller.admin.gugu.vo.subjectselection.SchoolListReqVO;
import cn.iocoder.yudao.module.system.controller.admin.gugu.vo.subjectselection.SubjectSelectionReqVO;
import cn.iocoder.yudao.module.system.controller.admin.gugu.vo.subjectselection.SubjectSelectionRespVO;
import cn.iocoder.yudao.module.system.dal.dataobject.collegeenrollmentplan.CollegeEnrollmentPlanDO;
import cn.iocoder.yudao.module.system.dal.mysql.collegeenrollmentplan.CollegeEnrollmentPlanMapper;
import cn.iocoder.yudao.module.system.util.gugu.SubjectCombinationCalculator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 选科功能服务实现类
 */
@Service
@Slf4j
public class SubjectSelectionServiceImpl implements SubjectSelectionService {

    @Resource
    private CollegeEnrollmentPlanMapper collegeEnrollmentPlanMapper;

    @Override
    public List<SubjectSelectionRespVO.MajorCategoryInfo> getMajorCategoryList(MajorCategoryListReqVO reqVO) {
        log.info("获取专业大类列表，参数：{}", reqVO);

        // 查询招生计划数据
        List<CollegeEnrollmentPlanDO> enrollmentPlans = collegeEnrollmentPlanMapper.selectMajorCategoriesWithStats(
                reqVO.getProvince(), reqVO.getYear(), reqVO.getEducationLevel(), reqVO.getType());

        // 按专业大类分组统计
        Map<String, List<CollegeEnrollmentPlanDO>> categoryMap = enrollmentPlans.stream()
                .filter(plan -> StringUtils.hasText(plan.getClassOne()))
                .collect(Collectors.groupingBy(CollegeEnrollmentPlanDO::getClassOne));

        List<SubjectSelectionRespVO.MajorCategoryInfo> result = new ArrayList<>();

        for (Map.Entry<String, List<CollegeEnrollmentPlanDO>> entry : categoryMap.entrySet()) {
            String categoryName = entry.getKey();
            List<CollegeEnrollmentPlanDO> plans = entry.getValue();

            SubjectSelectionRespVO.MajorCategoryInfo categoryInfo = calculateCategoryInfo(categoryName, plans);
            result.add(categoryInfo);
        }

        // 按匹配率降序排序
        result.sort((a, b) -> {
            String rateA = a.getMatchRate().replace("%", "");
            String rateB = b.getMatchRate().replace("%", "");
            try {
                return Double.compare(Double.parseDouble(rateB), Double.parseDouble(rateA));
            } catch (NumberFormatException e) {
                return 0;
            }
        });

        log.info("获取到{}个专业大类", result.size());
        return result;
    }

    @Override
    public List<SubjectSelectionRespVO.SchoolInfo> getSchoolList(SchoolListReqVO reqVO) {
        log.info("获取学校列表，参数：{}", reqVO);

        // 查询招生计划数据
        List<CollegeEnrollmentPlanDO> enrollmentPlans = collegeEnrollmentPlanMapper.selectSchoolsWithStats(
                reqVO.getProvince(), reqVO.getYear(), reqVO.getEducationLevel(), reqVO.getType(),
                reqVO.getSchoolNameKeyword(), reqVO.getMajorCategory());

        // 按学校分组统计
        Map<String, List<CollegeEnrollmentPlanDO>> schoolMap = enrollmentPlans.stream()
                .filter(plan -> StringUtils.hasText(plan.getSchoolName()))
                .collect(Collectors.groupingBy(CollegeEnrollmentPlanDO::getSchoolName));

        List<SubjectSelectionRespVO.SchoolInfo> result = new ArrayList<>();

        for (Map.Entry<String, List<CollegeEnrollmentPlanDO>> entry : schoolMap.entrySet()) {
            String schoolName = entry.getKey();
            List<CollegeEnrollmentPlanDO> plans = entry.getValue();

            SubjectSelectionRespVO.SchoolInfo schoolInfo = calculateSchoolInfo(schoolName, plans);
            result.add(schoolInfo);
        }

        // 按匹配率降序排序
        result.sort((a, b) -> {
            String rateA = a.getMatchRate().replace("%", "");
            String rateB = b.getMatchRate().replace("%", "");
            try {
                return Double.compare(Double.parseDouble(rateB), Double.parseDouble(rateA));
            } catch (NumberFormatException e) {
                return 0;
            }
        });

        log.info("获取到{}个学校", result.size());
        return result;
    }

    @Override
    public SubjectSelectionRespVO calculateOptimalSubjectCombination(SubjectSelectionReqVO reqVO) {
        log.info("计算最优选科组合，参数：{}", reqVO);

        SubjectSelectionRespVO response = new SubjectSelectionRespVO();
        response.setCalculationType(reqVO.getCalculationType());

        if ("school".equals(reqVO.getCalculationType())) {
            // 按学校计算
            List<SubjectSelectionRespVO.SchoolInfo> schoolInfos = new ArrayList<>();

            // 获取每个选择的学校的详细信息
            if (reqVO.getSelectedSchools() != null) {
                for (String schoolName : reqVO.getSelectedSchools()) {
                    SubjectSelectionRespVO.SchoolInfo schoolInfo = getSchoolInfo(
                            schoolName, reqVO.getProvince(), reqVO.getYear(), reqVO.getEducationLevel(), reqVO.getType());
                    if (schoolInfo != null) {
                        schoolInfos.add(schoolInfo);
                    }
                }
            }

            response.setSchools(schoolInfos);

            // 计算最优选科组合（基于学校）
            List<String> optimalCombination = calculateOptimalCombinationBySchools(reqVO);
            response.setOptimalSubjectCombination(optimalCombination);

            // 计算总体统计信息（基于学校）
            calculateOverallStatsBySchools(response, schoolInfos);

        } else {
            // 按专业大类计算（原有逻辑）
            List<SubjectSelectionRespVO.MajorCategoryInfo> categoryInfos = new ArrayList<>();

            // 获取每个选择的专业大类的详细信息
            if (reqVO.getSelectedMajorCategories() != null) {
                for (String categoryName : reqVO.getSelectedMajorCategories()) {
                    SubjectSelectionRespVO.MajorCategoryInfo categoryInfo = getMajorCategoryInfo(
                            categoryName, reqVO.getProvince(), reqVO.getYear(), reqVO.getEducationLevel(), reqVO.getType());
                    if (categoryInfo != null) {
                        categoryInfos.add(categoryInfo);
                    }
                }
            }

            response.setMajorCategories(categoryInfos);

            // 计算最优选科组合
            List<String> optimalCombination = calculateOptimalCombination(reqVO);
            response.setOptimalSubjectCombination(optimalCombination);

            // 计算总体统计信息
            calculateOverallStats(response, categoryInfos);
        }

        log.info("计算完成，最优组合：{}", response.getOptimalSubjectCombination());
        return response;
    }

    @Override
    public SubjectSelectionRespVO.MajorCategoryInfo getMajorCategoryInfo(String categoryName, String province, 
                                                                         Integer year, String educationLevel, String type) {
        // 查询指定专业大类的招生计划数据
        List<CollegeEnrollmentPlanDO> plans = collegeEnrollmentPlanMapper.selectByMajorCategory(
                categoryName, province, year, educationLevel, type);

        if (plans.isEmpty()) {
            return null;
        }

        return calculateCategoryInfo(categoryName, plans);
    }

    @Override
    public SubjectSelectionRespVO.SchoolInfo getSchoolInfo(String schoolName, String province,
                                                           Integer year, String educationLevel, String type) {
        // 查询指定学校的招生计划数据
        List<CollegeEnrollmentPlanDO> plans = collegeEnrollmentPlanMapper.selectBySchoolName(
                schoolName, province, year, educationLevel, type);

        if (plans.isEmpty()) {
            return null;
        }

        return calculateSchoolInfo(schoolName, plans);
    }

    /**
     * 计算专业大类信息
     */
    private SubjectSelectionRespVO.MajorCategoryInfo calculateCategoryInfo(String categoryName,
                                                                           List<CollegeEnrollmentPlanDO> plans) {
        SubjectSelectionRespVO.MajorCategoryInfo categoryInfo = new SubjectSelectionRespVO.MajorCategoryInfo();
        categoryInfo.setCategoryName(categoryName);

        // 统计专业数量（去重）
        Set<String> uniqueMajors = plans.stream()
                .map(CollegeEnrollmentPlanDO::getCollegeMajorName)
                .filter(StringUtils::hasText)
                .collect(Collectors.toSet());
        categoryInfo.setMajorCount(uniqueMajors.size());

        // 统计开设院校数（去重）
        Set<String> uniqueColleges = plans.stream()
                .map(CollegeEnrollmentPlanDO::getSchoolName)
                .filter(StringUtils::hasText)
                .collect(Collectors.toSet());
        categoryInfo.setCollegeCount(uniqueColleges.size());

        // 使用新的选科组合计算器
        List<String> subjectRequirements = plans.stream()
                .map(CollegeEnrollmentPlanDO::getCourseSelectionRequirements)
                .filter(StringUtils::hasText)
                .collect(Collectors.toList());

        SubjectCombinationCalculator.CombinationAnalysis analysis =
                SubjectCombinationCalculator.calculateOptimalCombination(subjectRequirements);

        categoryInfo.setOptimalCombination(String.join("、", analysis.getCombination()));
        categoryInfo.setMatchRate(String.format("%.0f%%", analysis.getCoverageRate()));

        // 设置描述信息
        categoryInfo.setDescription(String.format("%s > %s类 %d个专业",
                categoryName, categoryName, uniqueMajors.size()));

        return categoryInfo;
    }



    /**
     * 计算最优选科组合（跨专业大类）
     */
    private List<String> calculateOptimalCombination(SubjectSelectionReqVO reqVO) {
        // 收集所有选择的专业大类的选科要求
        List<String> allSubjectRequirements = new ArrayList<>();

        for (String categoryName : reqVO.getSelectedMajorCategories()) {
            List<CollegeEnrollmentPlanDO> plans = collegeEnrollmentPlanMapper.selectByMajorCategory(
                    categoryName, reqVO.getProvince(), reqVO.getYear(), reqVO.getEducationLevel(), reqVO.getType());

            List<String> categoryRequirements = plans.stream()
                    .map(CollegeEnrollmentPlanDO::getCourseSelectionRequirements)
                    .filter(StringUtils::hasText)
                    .collect(Collectors.toList());

            allSubjectRequirements.addAll(categoryRequirements);
        }

        // 使用选科组合计算器计算最优组合
        SubjectCombinationCalculator.CombinationAnalysis analysis =
                SubjectCombinationCalculator.calculateOptimalCombination(allSubjectRequirements);

        return analysis.getCombination();
    }

    /**
     * 计算学校信息
     */
    private SubjectSelectionRespVO.SchoolInfo calculateSchoolInfo(String schoolName,
                                                                 List<CollegeEnrollmentPlanDO> plans) {
        SubjectSelectionRespVO.SchoolInfo schoolInfo = new SubjectSelectionRespVO.SchoolInfo();
        schoolInfo.setSchoolName(schoolName);

        // 获取学校UUID（取第一个非空的）
        String schoolUuid = plans.stream()
                .map(CollegeEnrollmentPlanDO::getSchoolUuid)
                .filter(StringUtils::hasText)
                .findFirst()
                .orElse("");
        schoolInfo.setSchoolUuid(schoolUuid);

        // 统计专业数量（去重）
        Set<String> uniqueMajors = plans.stream()
                .map(CollegeEnrollmentPlanDO::getCollegeMajorName)
                .filter(StringUtils::hasText)
                .collect(Collectors.toSet());
        schoolInfo.setMajorCount(uniqueMajors.size());

        // 统计专业大类（去重）
        Set<String> uniqueCategories = plans.stream()
                .map(CollegeEnrollmentPlanDO::getClassOne)
                .filter(StringUtils::hasText)
                .collect(Collectors.toSet());
        schoolInfo.setMajorCategories(new ArrayList<>(uniqueCategories));

        // 使用选科组合计算器
        List<String> subjectRequirements = plans.stream()
                .map(CollegeEnrollmentPlanDO::getCourseSelectionRequirements)
                .filter(StringUtils::hasText)
                .collect(Collectors.toList());

        SubjectCombinationCalculator.CombinationAnalysis analysis =
                SubjectCombinationCalculator.calculateOptimalCombination(subjectRequirements);

        schoolInfo.setOptimalCombination(String.join("、", analysis.getCombination()));
        schoolInfo.setMatchRate(String.format("%.0f%%", analysis.getCoverageRate()));

        // 设置描述信息
        schoolInfo.setDescription(String.format("%s 开设%d个专业，涵盖%d个专业大类",
                schoolName, uniqueMajors.size(), uniqueCategories.size()));

        return schoolInfo;
    }

    /**
     * 计算最优选科组合（基于学校）
     */
    private List<String> calculateOptimalCombinationBySchools(SubjectSelectionReqVO reqVO) {
        // 收集所有选择的学校的选科要求
        List<String> allSubjectRequirements = new ArrayList<>();

        if (reqVO.getSelectedSchools() != null) {
            for (String schoolName : reqVO.getSelectedSchools()) {
                List<CollegeEnrollmentPlanDO> plans = collegeEnrollmentPlanMapper.selectBySchoolName(
                        schoolName, reqVO.getProvince(), reqVO.getYear(), reqVO.getEducationLevel(), reqVO.getType());

                List<String> schoolRequirements = plans.stream()
                        .map(CollegeEnrollmentPlanDO::getCourseSelectionRequirements)
                        .filter(StringUtils::hasText)
                        .collect(Collectors.toList());

                allSubjectRequirements.addAll(schoolRequirements);
            }
        }

        // 使用选科组合计算器计算最优组合
        SubjectCombinationCalculator.CombinationAnalysis analysis =
                SubjectCombinationCalculator.calculateOptimalCombination(allSubjectRequirements);

        return analysis.getCombination();
    }

    /**
     * 计算总体统计信息（基于学校）
     */
    private void calculateOverallStatsBySchools(SubjectSelectionRespVO response,
                                               List<SubjectSelectionRespVO.SchoolInfo> schoolInfos) {
        if (schoolInfos.isEmpty()) {
            response.setOverallMatchRate("0%");
            response.setTotalColleges(0);
            return;
        }

        // 计算总学校数
        response.setTotalColleges(schoolInfos.size());

        // 计算平均匹配率
        double avgMatchRate = schoolInfos.stream()
                .mapToDouble(info -> {
                    String rate = info.getMatchRate().replace("%", "");
                    try {
                        return Double.parseDouble(rate);
                    } catch (NumberFormatException e) {
                        return 0.0;
                    }
                })
                .average()
                .orElse(0.0);

        response.setOverallMatchRate(String.format("%.0f%%", avgMatchRate));
    }

    /**
     * 计算总体统计信息
     */
    private void calculateOverallStats(SubjectSelectionRespVO response, 
                                      List<SubjectSelectionRespVO.MajorCategoryInfo> categoryInfos) {
        if (categoryInfos.isEmpty()) {
            response.setOverallMatchRate("0%");
            response.setTotalColleges(0);
            return;
        }

        // 计算总开设院校数
        int totalColleges = categoryInfos.stream()
                .mapToInt(SubjectSelectionRespVO.MajorCategoryInfo::getCollegeCount)
                .sum();
        response.setTotalColleges(totalColleges);

        // 计算平均匹配率
        double avgMatchRate = categoryInfos.stream()
                .mapToDouble(info -> {
                    String rate = info.getMatchRate().replace("%", "");
                    try {
                        return Double.parseDouble(rate);
                    } catch (NumberFormatException e) {
                        return 0.0;
                    }
                })
                .average()
                .orElse(0.0);
        
        response.setOverallMatchRate(String.format("%.0f%%", avgMatchRate));
    }
}
